<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    /*
      原型：
        原型指的是两个原型属性：显示原型属性 prototype 和 隐式原型属性 __proto__

        显示原型属性: 
          (除了箭头函数以外)所有函数都有显示原型属性，它的值叫做原型对象。
          原型对象上默认有constructor方法，指向函数本身，还有一个隐式原型属性，指向Object原型对象
          
        隐式原型属性：
          所有对象（包括函数、数组）都是隐式原型属性，它的值指向其构造函数的原型对象

        还有两个特殊情况：  
          Object的原型对象上隐式原型属性的值是null，这个是原型链的尽头(Object.prototype.__proto__ === null)
          Function的隐式原型指向Function的显示原型（原型对象）（Function.prototype === Function.__proto__）


      原型链：
        概念：多个隐式原型属性组成结构，就是原型链
        作用：用来查找对象属性或方法
        具体规则：
          1. 先从自身属性上找，找到返回值
          2. 没有找到，沿着隐式原型属性上查找，找到返回值
          3. 如果多个隐式原型属性上都没有找到，最后找到 Object.prototype.__proto__, 值为null，但是返回值为undefined
    */

  // 原题目：
  function Foo() {
    getName = function () {
      console.log(1);
    };
    return this;
  }
  Foo.getName = function () {
    console.log(2);
  };
  Foo.prototype.getName = function () {
    console.log(3);
  };
  var getName = function () {
    console.log(4);
  };
  function getName() {
    console.log(5);
  }

  Foo.getName();
  getName();
  Foo().getName();
  getName();

  new Foo.getName();
  new Foo().getName();
  new new Foo().getName();

  // 解析

  // 函数是整体提升
  // function Foo(){
  //   getName = function(){console.log(1)}
  //   return this
  // }

  // function getName(){console.log(5)} // 被下面重新赋值了
  // var getName
  // 变量是声明提示

  /********* 预解析、预处理 *********/

  // Foo.getName = function(){console.log(2)}
  // Foo.prototype.getName = function(){console.log(3)}
  // // getName = function(){console.log(4)}
  // getName = function(){console.log(1)}

  // Foo.getName() // 2
  // getName() // 4
  // // getName = function(){console.log(1)} -> 找到全局getName并赋值
  // // window.getName()
  // Foo().getName() // 1
  // getName() // 1

  // new Foo.getName() // 2
  // new Foo().getName() // 3
  // new new Foo().getName() // new Foo() -> new Foo().getName -> new new Foo().getName() // 3

  </script>
</body>
</html>